package cn.keyvalue.ccf.common.http;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

public class NewRequestUtils {

	public final static int MAX_TOTAL_CONNECTIONS = 10;
	public final static int MAX_ROUTE_CONNECTIONS = 400;

	public final static int RETURNTYPE_STATUS_CODE = 1;
	public final static int RETURNTYPE_CONTENT = 2;

	public final static String METHOD_GET = "get";
	public final static String METHOD_POST = "post";

	public static String[] userAgentArray = new String[] {
			"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)",
			"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
			"Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)",
			"Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1",
			"Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3",
			"Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12",
			"Opera/9.27 (Windows NT 5.2; U; zh-cn)",
			"Opera/8.0 (Macintosh; PPC Mac OS X; U; en)",
			"Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0",
			"Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13",
			"Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3",
			"Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13",
			"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)",
			"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 360se)",
			"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; TencentTraveler 4.0; .NET CLR 2.0.50727)" };

	public static String getRandomUserAgent() {
		int random = RandomUtils.nextInt(userAgentArray.length);
		return userAgentArray[random];
	}

	public static HttpClient getHttpClient(String userAgent,
			int connectionTimeout, int soTimeout) {
		HttpConnectionManager manager = new SimpleHttpConnectionManager();

		HttpClient client = new HttpClient(manager);

		client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
				new DefaultHttpMethodRetryHandler());

		// 设置user-agent
		if (StringUtils.isNotEmpty(userAgent)) {
			client.getParams().setParameter(HttpMethodParams.USER_AGENT,
					userAgent);
		}

		// 设置cookie策略
		client.getParams().setCookiePolicy(CookiePolicy.DEFAULT);

		// 设置超时时间
		HttpConnectionManagerParams managerParams = client
				.getHttpConnectionManager().getParams();
		managerParams.setConnectionTimeout(connectionTimeout);
		managerParams.setSoTimeout(soTimeout);
		managerParams.setMaxTotalConnections(MAX_TOTAL_CONNECTIONS);
		// managerParams.setMaxConnectionsPerHost(20);
		// managerParams.setMaxConnectionsPerHost(hostConfiguration,
		// maxHostConnections)
		// managerParams.se

		return client;
	}

	public static void closeHttpClient(HttpClient client) {
		client.getHttpConnectionManager().closeIdleConnections(0);
	}

	/**
	 * 
	 * @param url
	 * @param encode
	 * @param userAgent
	 * @param time1
	 * @param time2
	 * @return
	 * @throws Exception
	 */
	public static String urlToStr(HttpClient client, String url, String method,
			NameValuePair[] nameValuePairs, Cookie[] cookies, int returntype)
			throws Exception {

		HttpMethodBase httpMethod = null;
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			if (StringUtils.equalsIgnoreCase(method, "get")) {
				httpMethod = new GetMethod(url);
				httpMethod.setFollowRedirects(true);
			} else {
				httpMethod = new PostMethod(url);
			}

			// 参数处理
			if (nameValuePairs != null && nameValuePairs.length > 0) {
				if (StringUtils.equalsIgnoreCase(method, "get")) {
					((GetMethod) httpMethod).setQueryString(nameValuePairs);
				} else {
					((PostMethod) httpMethod).addParameters(nameValuePairs);
				}
			}

			// Cookie处理,，由于使用的上下文，估计使用会很少
			if (cookies != null && cookies.length > 0) {
				HttpState initialState = new HttpState();
				initialState.addCookies(cookies);
				client.setState(initialState);
			}

			int status = client.executeMethod(httpMethod);

			if (returntype == RETURNTYPE_STATUS_CODE) {
				str = Integer.toString(status);

				// System.out
				// .println(ArrayUtils.toString(httpMethod.getResponseHeaders()));

			} else {
				String responsecharset = httpMethod.getResponseCharSet();
				// System.out.println("响应编码=" + responsecharset);

				if (StringUtils.equalsIgnoreCase(responsecharset, "gbk")
						|| StringUtils.equalsIgnoreCase(responsecharset,
								"gb2312")) {
					str = IOUtils.toString(
							httpMethod.getResponseBodyAsStream(),
							responsecharset);
				} else {

					// int contentLength = 0;
					// for (Header h : httpMethod.getResponseHeaders())
					// {
					// if(
					// StringUtils.equalsIgnoreCase(h.getName(),"Content-Length")
					// )
					// {
					// contentLength = NumberUtils.toInt(h.getValue());
					// break;
					// }
					// }
					// System.out.println(contentLength);

					InputStream is11 = httpMethod.getResponseBodyAsStream();
					// //读取为byte[]
					// ByteArrayOutputStream fos = new ByteArrayOutputStream();
					// int arraylength = 1024;
					// byte[] bs = new byte[arraylength];
					// int writeNum = 0;
					// int total = 0;
					// while ((writeNum = is11.read(bs)) != -1) {
					// total += writeNum;
					// if (writeNum == arraylength) {
					// fos.write(bs);
					// } else {
					// byte[] bs1 = new byte[writeNum];
					// System.arraycopy(bs, 0, bs1, 0, writeNum);
					// fos.write(bs1);
					// }
					// }

					// System.out.println( total );

					str = IOUtils.toString(is11, responsecharset);
					// System.out.println( str );

					String trueCharset = StringUtils.substringBetween(str,
							"charset=", "\"");
					if (StringUtils.isEmpty(trueCharset)
							|| StringUtils
									.containsIgnoreCase(trueCharset, "\"")) {
						trueCharset = StringUtils.substringBetween(str,
								"charset=\"", "\"");
					}
					if (StringUtils.containsIgnoreCase(trueCharset, "&")) {
						trueCharset = StringUtils.substringBefore(trueCharset,
								"&");
					}

					// System.out.println( str.substring(0,500) );
					// System.out.println("页面中显示的响应编码=" + trueCharset);

					// System.out.println("页面中显示的响应编码=" + responsecharset);
					// System.out.println("页面中显示的响应编码=" + trueCharset);
					if (!StringUtils.equalsIgnoreCase(responsecharset,
							trueCharset) && trueCharset != null) {
						str = new String(str.getBytes(responsecharset),
								trueCharset);
					}

					// System.out
					// .println(ArrayUtils.toString(httpMethod.getResponseHeaders()));
				}

				// System.out
				// .println(ArrayUtils.toString(httpMethod.getResponseHeaders()));

				// System.out.println( str.substring(0,200) );
			}

		} catch (Exception ee) {

			// e.printStackTrace();
			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (is != null) {
				is.close();
				is = null;
			}
			if (httpMethod != null) {
				httpMethod.releaseConnection();
				httpMethod = null;
			}
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	/**
	 * 带参数请求，返回内容
	 * 
	 * @param client
	 * @param url
	 * @param method
	 * @param nameValuePairs
	 * @return
	 * @throws Exception
	 */
	public static String urlToStr(HttpClient client, String url, String method,
			NameValuePair[] nameValuePairs) throws Exception {

		return urlToStr(client, url, method, nameValuePairs, null,
				RETURNTYPE_CONTENT);
	}

	/**
	 * 带Cookie请求，返回内容
	 * 
	 * @param client
	 * @param url
	 * @param method
	 * @return
	 * @throws Exception
	 */
	public static String urlToStr(HttpClient client, String url, String method)
			throws Exception {

		return urlToStr(client, url, method, null, null, RETURNTYPE_CONTENT);
	}

	/**
	 * 请求，返回响应码，适用于上下文的中间环节，无需知道响应内容
	 * 
	 * @param client
	 * @param url
	 * @param method
	 * @return
	 * @throws Exception
	 */
	public static int accessUrl(HttpClient client, String url, String method)
			throws Exception {

		return NumberUtils.toInt(urlToStr(client, url, method, null, null,
				RETURNTYPE_STATUS_CODE));
	}

	/**
	 * 请求，返回响应码，适用于上下文的中间环节，无需知道响应内容
	 * 
	 * @param client
	 * @param url
	 * @param method
	 * @return
	 * @throws Exception
	 */
	public static int accessUrl(HttpClient client, String url, String method,
			NameValuePair[] nameValuePairs) throws Exception {

		return NumberUtils.toInt(urlToStr(client, url, method, nameValuePairs,
				null, RETURNTYPE_STATUS_CODE));
	}

	/**
	 * 工具方法，获取cookie值
	 * 
	 * @param client
	 * @param cookieName
	 * @return
	 */
	public static String getCookieValue(HttpClient client, String cookieName) {
		Cookie[] cookies = client.getState().getCookies();

		if (!ArrayUtils.isEmpty(cookies)) {
			for (Cookie cookie : cookies) {
				if (StringUtils.equals(cookie.getName(), cookieName)) {
					return cookie.getValue();
				}
			}
		}

		return null;
	}

	/**
	 * 解析真实url，如果链接为跳转中间地址，则解析出最终地址 302目标地址
	 * 
	 * @param urlStr
	 * @return
	 * @throws IOException
	 * @throws HttpException
	 */
	public static String getTrueURL(String urlStr) throws HttpException,
			IOException {
		return getTrueURL(urlStr, 1);
	}

	private static String getTrueURL(String urlStr, int level)
			throws HttpException, IOException {
		String userAgent = NewRequestUtils.getRandomUserAgent();
		HttpClient httpClient = NewRequestUtils.getHttpClient(userAgent, 3000,
				3000);

		HttpMethod method = new GetMethod(urlStr);
		httpClient.executeMethod(method);

		String retURL = method.getURI().toString();

		// 最多到三层
		if (level < 3) {

			// 判断内容是否包含跳转
			Connection conn = Jsoup.connect(urlStr);
			Document doc = conn.get();
			
			Elements links = doc.select("meta[http-equiv=refresh]");

			if (links != null && !links.isEmpty()) {
				String value = links.get(0).attr("content");

				String httpurl_header = "http";
				if (StringUtils.contains(value, httpurl_header)) {
					String nexturl = httpurl_header
							+ StringUtils.trimToEmpty(StringUtils
									.substringAfterLast(value, httpurl_header));
					retURL = getTrueURL(nexturl, level + 1);
				}
			}

		}
		NewRequestUtils.closeHttpClient(httpClient);
		
		return StringUtils.trimToEmpty(retURL);
	}

	public static void main(String[] args) throws Exception {
		// 苏宁 详情 京东 详情 活动 库巴 详情 一号店 详情 当当 详情 亚马逊 详情 活动 银泰 首页 优购 首页 唯品会 首页 红孩子 首页
		// 新蛋 首页
		// 乐淘 首页 凡客 首页 国美 首页 51buy 首页

		suningshiwu();

	}

	public static void amazonshiwu() throws Exception {
		// 1.访问首页得到两个cookie值
		String useragent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";
		HttpClient client = getHttpClient(useragent, 5000, 5000);

		String url = "http://m.amazon.cn";
		int code = accessUrl(client, url, "get");
		// System.out.println("code=" + code);

		// 2.获取两个数据
		String x_wl_uid = getCookieValue(client, "x-wl-uid");
		String session_id = getCookieValue(client, "session-id");
		// System.out.println("x-wl-uid=" + x_wl_uid);
		// System.out.println("session-id=" + session_id);

		// 3.构造参数
		NameValuePair[] nameValuePairs = null;
		NameValuePair nameValuePair = null;

		nameValuePair = new NameValuePair("o", "add");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);

		// nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
		// nameValuePair);
		nameValuePair = new NameValuePair("verificationSessionID", session_id);
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("oid", x_wl_uid);
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);

		// 4.请求获取页面内容
		url = "http://www.amazon.cn/gp/aw/c/ref=aw_d_c_wireless";

		nameValuePair = new NameValuePair("a", "B001OI25BY");
		code = accessUrl(client, url, "post",
				(NameValuePair[]) ArrayUtils.add(nameValuePairs, nameValuePair));
		System.out.println(code);

		nameValuePair = new NameValuePair("a", "B0037GUYZA");
		code = accessUrl(client, url, "post",
				(NameValuePair[]) ArrayUtils.add(nameValuePairs, nameValuePair));
		System.out.println(code);

		nameValuePair = new NameValuePair("a", "B007WPFJIY");
		String content = urlToStr(client, url, "post",
				(NameValuePair[]) ArrayUtils.add(nameValuePairs, nameValuePair));
		System.out.println(content);

		// 5.关闭
		closeHttpClient(client);
	}

	public static void suningshiwu() throws Exception {

		String useragent = getRandomUserAgent();
		HttpClient client = getHttpClient(useragent, 10000, 10000);

		NameValuePair[] nameValuePairs = null;
		NameValuePair nameValuePair = null;

		nameValuePair = new NameValuePair("quantity", "1");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("fullInventoryCheck", "0");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("inventoryCheckType", "0");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("fullVoucherCheck", "0");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("voucherCheckType", "0");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("inventoryRemoteCheck", "1");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("voucherRemoteCheck", "1");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("orderId", ".");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("URL", "OrderItemDisplay");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("ERROEVIEW",
				"prd_10052_10051_-7_2587169_.html");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("storeId", "10052");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("catalogId", "10051");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("isOldToNew", "0");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("isfourPageBuyNow", "0");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("sellType", "0");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("easilyBuyId", "-1");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);
		nameValuePair = new NameValuePair("returnURL",
				"http://www.suning.com/emall/prd_10052_10051_-7_2587169_.html");
		nameValuePairs = (NameValuePair[]) ArrayUtils.add(nameValuePairs,
				nameValuePair);

		// 加入购物车http://gate.360buy.com/InitCart.aspx?pid=1008569515&pcount=1&ptype=1
		String url = "https://cart.suning.com/emall/addMiniSoppingCart";
		System.out.println(url);

		nameValuePair = new NameValuePair("catEntryId_1", "2407040");
		int code = accessUrl(client, url, "post",
				(NameValuePair[]) ArrayUtils.add(nameValuePairs, nameValuePair));
		System.out.println(code);
		// nameValuePair = new NameValuePair("catEntryId_1", "384620");
		// code = accessUrl(client, url, "post" ,(NameValuePair[])
		// ArrayUtils.add(nameValuePairs,
		// nameValuePair));
		// System.out.println(code);
		// nameValuePair = new NameValuePair("catEntryId_1", "1768115");
		// code = accessUrl(client, url, "post" ,(NameValuePair[])
		// ArrayUtils.add(nameValuePairs,
		// nameValuePair));
		// System.out.println(code);
		// System.out.println(content);

		url = "https://cart.suning.com/emall/OrderItemDisplay";
		String content = urlToStr(client, url, "post");
		System.out.println("aaa" + content);

		closeHttpClient(client);

	}

	/**
	 * 京东购物车事物
	 * 
	 * @throws Exception
	 */
	public static void jingdongshiwu() throws Exception {
		String useragent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";
		HttpClient client = getHttpClient(useragent, 5000, 5000);

		// 加入购物车http://gate.360buy.com/InitCart.aspx?pid=1008569515&pcount=1&ptype=1
		String url = "http://gate.360buy.com/InitCart.aspx?pid=580925&pcount=1&ptype=1";
		System.out.println(url);
		urlToStr(client, url, "get");

		// 加入购物车
		url = "http://gate.360buy.com/InitCart.aspx?pid=124934&pcount=1&ptype=1";
		urlToStr(client, url, "get");

		// 查看购物车
		url = "http://cart.360buy.com/cart/getCurrentCartNew.action";
		String content = urlToStr(client, url, "get");
		System.out.println(content);

		closeHttpClient(client);
	}
}
